***************************************
* This Stata dofile is written to accompany the paper:
* Amy King & Andrew Leigh, 2009, 'Are Ballot Order Effects Heterogeneous?' Social Science Quarterly.
* Feel free to use or adapt it, so long as you cite that paper.
***************************************

version 10.0
clear
set more off
set mem 10m
cd "C:\Users\Andrew\My publications\Aust - beautiful politicians etc\"

/*

***************************************
* Setup
***************************************
* Setting up electorate demographics
use electoratedemographics1998.dta, clear
for any 2001 2004: append using electoratedemographicsX.dta
* Various electorates had been abolished by 1996. We match them with the demographics
* of the closest electorate.
for any "Namadgi (ACT)" "Dundas (NSW)" "Hawker (SA)" "Henty (Vic)" "Phillip (NSW)" "St. George (NSW)" "Streeton (Vic)" \ any "Fraser (ACT)" "Berowra (NSW)" "Hindmarsh (SA)" "Hotham (Vic)" "Grayndler (NSW)" "Barton (NSW)" "La Trobe (Vic)": expand 2 if electoraldivision=="Y" & election==1998 \ bysort electoraldivision: egen temp=seq() if electoraldivision=="Y" & election==1998 \ replace electoraldivision="X" if temp==2 \ drop temp
for any "St George (NSW)" \ any "St. George (NSW)": expand 2 if electoraldivision=="Y" & election==1998 \ bysort electoraldivision: egen temp=seq() if electoraldivision=="Y" & election==1998 \ replace electoraldivision="X" if temp==2 \ drop temp
gen electorate4=substr(electoraldivision,1,4)
replace electorate4="KiSm" if electoraldivision=="Kingsford Smith (NSW)" | electoraldivision=="Kingsford-Smith (NSW)" | electoraldivision=="Kingsford Smith"
replace electorate4="MePo" if electoraldivision=="Melbourne Ports (Vic)"
replace electorate4="BrFi" if electoraldivision=="Bradfield (NSW)"
replace electorate4="NTer" if electoraldivision=="Northern Territory (NT)"
* Changing naming to match Amy's coding
for any sharewithtertiaryquals sharewithnoquals sharewithtradequals medianfamilyincome sharewomeninlf \ any sharetertiary sharenoqual sharetradequal medianincome sharewomenlf: ren X Y
* Treating "share left school before 15 (1996 census) as equivalent to "less than year 10" (2001 census)
replace shareyr10below=shareleftschool15below if shareyr10below==.
drop shareleftschool15below 
* We assume demographics were unchanged from 1984-1998
expand 6 if election==1998 
bysort electorate4: egen temp=seq() if election==1998
replace election=temp if election==1998
recode election 1=1984 2=1987 3=1990 4=1993 5=1996 6=1998
drop temp
sort electorate4 election
save temp1, replace

* Setting up two-party-preferred vote
use two_party_vote_1996_2004.dta 
ren division electoraldivision
gen electorate4=substr(electoraldivision,1,4)
replace electorate4="KiSm" if electoraldivision=="Kingsford Smith (NSW)" | electoraldivision=="Kingsford-Smith (NSW)" | electoraldivision=="Kingsford Smith"
replace electorate4="MePo" if electoraldivision=="Melbourne Ports (Vic)"
replace electorate4="BrFi" if electoraldivision=="Bradfield (NSW)"
replace electorate4="NTer" if electoraldivision=="Northern Territory (NT)"
drop electoraldivision
reshape long cvote,i(electorate4) j(election)
sort electorate4 election
save temp2, replace

* Loading elections data
use elections1993_2004.dta, clear
for num 1984 1987 1990: append using "C:\Users\Andrew\Datasets\AEC data\X_sex"

* Merging on electorate characteristics
gen electorate4=substr(electorate,1,4)
replace electorate4="KiSm" if electorate=="Kingsford Smith (NSW)" | electorate=="Kingsford-Smith (NSW)" | electorate=="Kingsford - Smith (NSW)" | electorate=="Kingsford Smith"
replace electorate4="MePo" if electorate=="Melbourne Ports (Vic)"
replace electorate4="BrFi" if electorate=="Bradfield (NSW)"
replace electorate4="NTer" if electorate=="Northern Territory (NT)"
sort electorate4 election
merge electorate4 election using temp1, update nokeep
tab _merge
drop _merge

* Merging on Coalition vote
sort electorate4 election
merge electorate4 election using temp2, update nokeep
tab _merge
drop _merge 
* Calculating voteshare
bysort election electorate: egen totalvote=sum(primaryvote)
gen voteshare=primaryvote/totalvote
bysort election electorate: egen totalcandidates=max(ballotposition)
gen logvoteshare=ln(voteshare)

* Generating a candidate ID code
replace firstname="." if firstname==""
for any firstname lastname: replace X=proper(X)
egen candidate=group(firstname lastname)

* Generating sex
replace female=1 if gender=="F"
replace female=0 if gender=="M"
* For some reason, a couple of candidates did not have gender coded
replace female=0 if (firstname=="James Stephen" | firstname=="Chris" | firstname=="Cy") & female==.
replace female=1 if firstname=="Ros" & female==.
replace female=0 if firstname=="Steele" & lastname=="Hall"
list firstname election if female==.

* Generating party ID
replace party="IND" if party=="" 
egen partyno=group(party)
egen party_election=group(party election)

* Generating ballot order variables and interactions
gen relbalpos=(ballotposition/totalcandidates)
tab ballotposition, gen(balpos)

* ShareTertiary is missing for 2004, so we assume it was same as in 2001
bysort electorate: egen temp=max(sharetertiary)
replace sharetertiary=temp if sharetertiary==.
drop temp

* Summary statistics
tabstat voteshare logvoteshare balpos1 female sharenotfluent medianage medianincome, c(s) nosep s(mean sd n) format(%9.4f)
* Generating interactions (note that with the demographics, we first norm them to mean 0, SD 1)
for any sharenotfluent shareyr10below medianage medianincome sharetertiary: egen temp=std(X) \ replace X=temp \ drop temp
gen balpos1_hied=balpos1*sharetertiary
gen balpos1_lowed=balpos1*shareyr10below
gen balpos1_noteng=balpos1*sharenotfluent
gen balpos1_age=balpos1*medianage
gen balpos1_inc=balpos1*medianincome
gen balpos1_f=balpos1*female

* Generate "first woman" (only exists if >1 women on ballot paper)
bysort election electorate: egen temp1=min(ballotposition) if female==1
bysort election electorate: egen temp2=max(ballotposition) if female==1
gen firstwoman=1 if temp1==ballotposition & temp1~=temp2
recode firstwoman .=0 if female==1 & temp1~=ballotposition & temp1~=temp2
drop temp*

* Generating major party and minor party variables
gen majorparty=1 if party=="ALP" 
replace majorparty=1 if party=="LP"
replace majorparty=1 if party=="NP"
mvencode majorparty, mv(0)
gen balpos1_majorparty=balpos1*majorparty
gen minorparty=1 if party=="DEM"
replace minorparty=1 if party=="GRN"
mvencode minorparty, mv(0)
gen balpos1_minorparty=balpos1*minorparty
gen independent=0 if party=="ALP"
replace independent=0 if party=="LP"
replace independent=0 if party=="NP"
replace independent=0 if party=="DEM"
replace independent=0 if party=="GRN"
mvencode independent, mv(1)
gen balpos1_independent=balpos1*independent

save elections1984_2004_demographics.dta, replace 
*/

***************************************
* Ballot order regressions
***************************************

cd "C:\Users\Andrew\My publications\Aust - beautiful politicians etc\"
use elections1984_2004_demographics.dta, clear

* Number of candidates who run more than once
bysort candidate: egen n_elections=count(voteshare)
codebook candidate
codebook candidate if n_elections>1 & n_elections~=.

* Number of electorates per election
for num 1984 1987 1990 1993 1996 1998 2001 2004: codebook electorate if election==X

* Election-electorate groups (for clustering)
egen election_electorate=group(election electorate)

xi: reg voteshare balpos1 i.totalcandidates, cl(election_electorate)
outreg using balpos_results1.doc, coefastr nocons bracket 3aster replace bdec(4) se ct("Vote")
xi: areg voteshare balpos1 i.election i.totalcandidates, a(party) cl(election_electorate)
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote-elect&pty FE")
xi: areg voteshare balpos1 i.election i.party i.totalcandidates, a(candidate) cl(election_electorate)
outreg using balpos_results2.doc, coefastr nocons bracket 3aster replace bdec(4) se ct("Vote-elect&pty&cand FE")

xi: reg logvoteshare balpos1 i.totalcandidates, cl(election_electorate)
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote")
xi: areg logvoteshare balpos1 i.election i.totalcandidates, a(party) cl(election_electorate)
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote-elect&pty FE")
xi: areg logvoteshare balpos1 i.election i.party i.totalcandidates, a(candidate) cl(election_electorate)
outreg using balpos_results2.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote-elect&pty&cand FE")

* Candidate FE - those who run multiple times
xi: areg voteshare balpos1 i.election i.party i.totalcandidates if n_elections>1 & n_elections~=., a(candidate) cl(election_electorate)
xi: areg logvoteshare balpos1 i.election i.party i.totalcandidates if n_elections>1 & n_elections~=., a(candidate) cl(election_electorate)

* Across elections
for num 1984 1987 1990 1993 1996 1998 2001 2004: gen bp1_X=balpos1 if election==X \ recode bp1_X .=0
xi: areg voteshare bp1_* i.election i.totalcandidates, a(party) cl(election_electorate)
test bp1_1984=bp1_1987=bp1_1990=bp1_1993=bp1_1996=bp1_1998=bp1_2001=bp1_2004 
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)
xi: areg logvoteshare bp1_* i.election i.totalcandidates, a(party) cl(election_electorate)
test bp1_1984=bp1_1987=bp1_1990=bp1_1993=bp1_1996=bp1_1998=bp1_2001=bp1_2004
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)

gen bp1_year=balpos1*election
for any voteshare logvoteshare: xi: areg X balpos1 bp1_year i.election i.totalcandidates, a(party) cl(election_electorate) \ test bp1_year
drop bp1_year

* Across parties
xi: areg voteshare balpos1_majorparty balpos1_minorparty balpos1_independent i.totalcandidates i.election, a(party) cl(election_electorate)
test balpos1_major=balpos1_minor=balpos1_independent
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)
xi: areg logvoteshare balpos1_majorparty balpos1_minorparty balpos1_independent i.totalcandidates i.election, a(party) cl(election_electorate) 
test balpos1_major=balpos1_minor=balpos1_independent
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)

* Checking baseline vote and R2 by party
for any majorparty minorparty independent: sum voteshare if X==1,d
for any majorparty minorparty independent: qui xi: areg voteshare balpos1 i.totalcandidates i.election if X==1, a(party) cl(election_electorate) \ di "X Voteshare R2=" \ di e(r2) \ xi: areg logvoteshare balpos1 i.totalcandidates i.election if X==1, a(party) cl(election_electorate) \ di "X Log(Voteshare) R2=" \ di e(r2)

* Male & female
gen balpos1_m=balpos1 if female==0
recode balpos1_m .=0 if female~=.
xi: areg voteshare balpos1_m balpos1_f female i.totalcandidates i.election, a(party) cl(election_electorate)
test balpos1_m=balpos1_f
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)
xi: areg logvoteshare balpos1_m balpos1_f female i.totalcandidates i.election, a(party) cl(election_electorate)
test balpos1_m=balpos1_f
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)
#delimit ;
for any majorparty minorparty independent: xi: areg voteshare balpos1_m balpos1_f female i.totalcandidates i.election if X==1, a(party) cl(election_electorate) \
test balpos1_m=balpos1_f \
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote (X only)") addstat("F test",r(F),"P val on F-test",r(p)) adec(4) \
xi: areg logvoteshare balpos1_m balpos1_f female i.totalcandidates i.election if X==1, a(party) cl(election_electorate) \
test balpos1_m=balpos1_f \
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote (X only)") addstat("F test",r(F),"P val on F-test",r(p)) adec(4);
#delimit cr

* Firstwoman/firstman
drop firstwoman
bysort election_electorate: egen temp1=min(ballotposition) if female==1
gen firstwoman=1 if temp1==ballotposition & female==1 
bysort election_electorate: egen temp2=min(ballotposition) if female==0
gen firstman=1 if temp2==ballotposition & female==0 
for any firstwoman firstman: recode X .=0 if female~=.
drop temp*
xi: areg voteshare balpos1_m balpos1_f firstman firstwoman female i.totalcandidates i.election, a(party) cl(election_electorate)
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote")
xi: areg logvoteshare balpos1_m balpos1_f firstman firstwoman female i.totalcandidates i.election, a(party) cl(election_electorate)
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote")
#delimit ;
for any majorparty minorparty independent: xi: areg voteshare balpos1_m balpos1_f firstman firstwoman female i.totalcandidates i.election if X==1, a(party) cl(election_electorate) \
test balpos1_m=balpos1_f \
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote (X only)") addstat("F test",r(F),"P val on F-test",r(p)) adec(4) \
xi: areg logvoteshare balpos1_m balpos1_f firstman firstwoman female i.totalcandidates i.election if X==1, a(party) cl(election_electorate) \
test balpos1_m=balpos1_f \
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote (X only)") addstat("F test",r(F),"P val on F-test",r(p)) adec(4);
#delimit cr

* By electorate characteristics - individually
for any noteng age inc \ any sharenotfluent medianage medianincome : xi: areg voteshare balpos1 balpos1_X Y i.election i.totalcandidates, a(party) cl(electorate4) \ outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote")
for any noteng age inc \ any sharenotfluent medianage medianincome : xi: areg logvoteshare balpos1 balpos1_X Y i.election i.totalcandidates, a(party) cl(electorate4) \ outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote")
* By electorate characteristics - together
xi: areg voteshare balpos1 balpos1_noteng balpos1_age balpos1_inc sharenotfluent medianage medianincome i.election i.totalcandidates, a(party) cl(electorate4)
testparm balpos1_*
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("Vote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)
xi: areg logvoteshare balpos1 balpos1_noteng balpos1_age balpos1_inc sharenotfluent medianage medianincome i.election i.totalcandidates, a(party) cl(electorate4)
testparm balpos1_*
outreg using balpos_results1.doc, coefastr nocons bracket 3aster append bdec(4) se ct("LogVote") addstat("F test",r(F),"P val on F-test",r(p)) adec(4)

* Testing ballot order effects electorate-by-electorate
gen b_elect=.
gen se_elect=.
levelsof electorate4, local(electorate)
foreach e of local electorate {
	areg voteshare balpos1 if electorate4=="`e'", a(totalcandidates) 
	replace b_elect=_b[balpos1] if e(sample)
	replace se_elect=_se[balpos1] if e(sample)
	}
gen t_elect=b_elect/se_elect
egen tag=tag(electorate4)
list electorate b_elect t_elect if tag

***************************************
* When was ballot order pivotal? 
***************************************
* Here, we use the variable "cvote", which is the Coalition's two-party-preferred voteshare
gen margin=abs(cvote-50)
drop tag
egen tag=tag(election electorate)
sum margin if tag,d
for num 1 \ any 1: gen marginY=margin \ recode marginY 0/X=1 .=. *=0 
tab margin1 if tag
* All <1% races
list election electorate party cvote female if margin1==1 & balpos1==1 
* List all major party candidates with less than a 1% margin
list firstname lastname election electorate party cvote female if margin1==1 & balpos1==1 & (((party=="LP" | party=="NP" | party=="CLP") & cvote>50) | (party=="ALP" & cvote<50))

